#include "delegates.h"
#include "complexeditor.h"
#include "matrix.h"
#include "matrixsheet.h"

#include <QSpinBox>
#include <QDoubleSpinBox>

static const int Decimals = 15;

BaseDelegate::BaseDelegate(MatrixSheet *sheet) : QItemDelegate((QObject*)sheet), m_matrixSheet(sheet)
{

}

SpinBoxDelegate::SpinBoxDelegate(MatrixSheet *sheet)
    : BaseDelegate(sheet)
{
}

QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(INT_MIN);
    editor->setMaximum(INT_MAX);
    return editor;
}

void SpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->setValue(value);
}

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();

    model->setData(index, value, Qt::EditRole);
}

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
DoubleSpinBoxDelegate::DoubleSpinBoxDelegate(MatrixSheet *sheet)
    : BaseDelegate(sheet)
{
}

QWidget *DoubleSpinBoxDelegate::createEditor(QWidget *parent,
                                             const QStyleOptionViewItem &/* option */,
                                             const QModelIndex &/* index */) const
{
    QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
    editor->setDecimals(Decimals);
    editor->setFrame(false);
    editor->setMinimum(-DBL_MAX);
    editor->setMaximum(DBL_MAX);
    return editor;
}

void DoubleSpinBoxDelegate::setEditorData(QWidget *editor,
                                          const QModelIndex &index) const
{
    double value = index.model()->data(index, Qt::EditRole).toDouble();
    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->setMinimum(-DBL_MAX);
    spinBox->setMaximum(DBL_MAX);
    spinBox->setDecimals(Decimals);
    spinBox->setValue(value);
}

void DoubleSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                         const QModelIndex &index) const
{
    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->setMinimum(-DBL_MAX);
    spinBox->setMaximum(DBL_MAX);
    spinBox->setDecimals(Decimals);
    double value = spinBox->value();
    model->setData(index, value, Qt::EditRole);
}

void DoubleSpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                 const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
ComplexSpinBoxDelegate::ComplexSpinBoxDelegate(MatrixSheet *sheet)
    : BaseDelegate(sheet)
{
}

QWidget *ComplexSpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    ComplexEditor *editor = new ComplexEditor(parent);
    return editor;
}

void ComplexSpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    ComplexEditor *spinBox = static_cast<ComplexEditor*>(editor);
    if (m_matrixSheet->matrix()->type() == MatrixBase::ComplexDouble) {
        ComplexDoubleType value = qvariant_cast<ComplexDoubleType>(index.model()->data(index, Qt::EditRole));
        spinBox->setValue(value);
    } else {
        ComplexFloatType value = qvariant_cast<ComplexFloatType>(index.model()->data(index, Qt::EditRole));
        spinBox->setValue(value);
    }
}

void ComplexSpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    ComplexEditor *spinBox = static_cast<ComplexEditor*>(editor);
    QVariant value = QVariant::fromValue<ComplexDoubleType>(spinBox->value());
    model->setData(index, value, Qt::EditRole);
}

void ComplexSpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                                  const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}
